# --------------------------------------------------------------------------------------------------------------------
# Project:             Digital Payment System (DPS)
# Website:             http://code.google.com/p/dps-x509/
# Purpose of document: This class constructs an x.509 certificate
# --------------------------------------------------------------------------------------------------------------------
import sys, string, logging, base64, os
from time import time
sys.path.append("..")

from pyasn1.type import tag, namedtype, namedval, univ, constraint, char, useful
from pyasn1.codec.der import decoder, encoder
from pyasn1 import error

import keyczar.keys
import keyczar.util

import dps.x509Asn1Extractor
import dps.errors
import dps.utils
import dps.asn1CertificateSpecification

#c = dps.asn1CertificateSpecification.Asn1CertificateSpecification()
#sigAsn = c.getComponentByName("tbsCertificate").getComponentByName("signature")
#setComponentByName

#get our private key...
privateKey = None
if not os.path.isfile("pk.txt"):
  t0 = time()
  privateKey = keyczar.keys.RsaPrivateKey.Generate()
  t1 = time()
  print ("private key generation took %f seconds" %(t1 - t0))
  pk = str(privateKey)
  keyczar.util.WriteFile(pk, "pk.txt")
else:
  pk = keyczar.util.ReadFile("pk.txt")
  privateKey = keyczar.keys.RsaPrivateKey.Read(pk)

mod = keyczar.util.BytesToLong(privateKey.public_key.params["modulus"])
publicExp = keyczar.util.BytesToLong(privateKey.public_key.params["publicExponent"])

params = {"n": mod, "e": publicExp}
subjectPublicKeyInfoAsn = decoder.decode(keyczar.util.Decode(keyczar.util.ExportRsaX509(params)))[0]
print subjectPublicKeyInfoAsn
  
#build from the bottom up

#Time
#utcTime = useful.UTCTime("030930161343Z")
#generalTime = useful.GeneralizedTime("370930161344Z")

#Validity
#notBefore = keyczar.util.ASN1Sequence(utcTime, generalTime)
#notAfter = keyczar.util.ASN1Sequence(utcTime, generalTime)

#signatureAlgorithm members
#algorithm = keyczar.util.SHA1RSA_OID
#parameters = univ.Null()

#tbsCertificate members
#version = namedtype.DefaultedNamedType('version', dps.asn1CertificateSpecification.Version(3, 
#                                       tagSet=dps.asn1CertificateSpecification.Version.tagSet.tagExplicitly(
#                                       tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))))
#version = namedval.NamedValues(("v3", 2))
#serialNumber = univ.Integer(0)
#signature = keyczar.util.ASN1Sequence(algorithm, parameters)

#issuerType = univ.ObjectIdentifier("10")
#issuerValue = univ.Null()

#issuerSet = univ.SetOf(univ.Sequence(issuerType, issuerValue))
#issuerSeq = univ.SequenceOf(issuerSet)
#issuer = univ.Choice(componentType= namedtype.NamedTypes(
#                     namedtype.NamedType("", univ.Null())))

#validity = keyczar.util.ASN1Sequence(notBefore, notAfter)
#subject = univ.Choice()

#certificate root members
#tbsCertificate = keyczar.util.ASN1Sequence(version, serialNumber, signature, issuer, validity, subject, subjectPublicKeyInfo)
#tbsCertificate = keyczar.util.ASN1Sequence(serialNumber, signature, validity, subjectPublicKeyInfo)

#signatureAlgorithm = keyczar.util.ASN1Sequence(algorithm, parameters)
#binkey = BytesToBin(encoder.encode(key))
#pubkey = univ.BitString("'%s'B" % binkey)

#certBytes = encoder.encode(version)
#certBytes = encoder.encode(serialNumber)
#certBytes = encoder.encode(signature)
#certBytes = encoder.encode(issuer)
#certBytes = encoder.encode(validity)
#certBytes = encoder.encode(subject)
#certBytes = encoder.encode(subjectPublicKeyInfo)
#certBytes = encoder.encode(signatureAlgorithm)
#certBytes = encoder.encode(tbsCertificate)

#certAsn = keyczar.util.ASN1Sequence(tbsCertificate, signatureAlgorithm, signatureValue)
#print certAsn.prettyPrint()

#certBase64 = base64.b64encode(encoder.encode(certAsn))
#keyczar.util.WriteFile(certBase64, "my.crt")
#print certBase64

templateBase64 = keyczar.util.ReadFile("testbase64.crt")

#create from template
certBytes = keyczar.util.Decode(dps.x509Asn1Extractor.certToBase64(templateBase64))
certAsn = decoder.decode(certBytes, \
                         asn1Spec=dps.asn1CertificateSpecification.Asn1CertificateSpecification())[0]

#change any of the fields here

#print "before"
#print as1Cert.getComponentByName("tbsCertificate").getComponentByName("subjectPublicKeyInfo")

#add the public key to the certificate
tbsCertificateAsn = certAsn.getComponentByName("tbsCertificate")
tbsCertificateAsn.setComponentByName("subjectPublicKeyInfo", subjectPublicKeyInfoAsn)
certAsn.setComponentByName("tbsCertificate", tbsCertificateAsn)
#print "after"
#print as1Cert.getComponentByName("tbsCertificate").getComponentByName("subjectPublicKeyInfo")

#sign the certificate
tbsCertificateAsn = certAsn.getComponentByName("tbsCertificate")
certBytes = encoder.encode(tbsCertificateAsn)
sigBytes = privateKey.Sign(certBytes)
sigBin = keyczar.util.BytesToBin(sigBytes)
signatureValue = univ.BitString("'%s'B" % sigBin)  # needs to be a BIT STRING  

certAsn.setComponentByName("signatureValue", signatureValue)


certBase64 = base64.b64encode(encoder.encode(certAsn))
keyczar.util.WriteFile(certBase64, "my_2.crt")



